{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "code",
      "source": [
        "!pip install -q streamlit langchain langchain-google-genai langchain-community\n",
        "!pip install -q pyngrok python-dotenv wikipedia duckduckgo-search\n",
        "!npm install -g localtunnel\n",
        "\n",
        "import streamlit as st\n",
        "import os\n",
        "from langchain_google_genai import ChatGoogleGenerativeAI\n",
        "from langchain.agents import create_react_agent, AgentExecutor\n",
        "from langchain.tools import Tool, WikipediaQueryRun, DuckDuckGoSearchRun\n",
        "from langchain.memory import ConversationBufferWindowMemory\n",
        "from langchain.prompts import PromptTemplate\n",
        "from langchain.callbacks.streamlit import StreamlitCallbackHandler\n",
        "from langchain_community.utilities import WikipediaAPIWrapper, DuckDuckGoSearchAPIWrapper\n",
        "import asyncio\n",
        "import threading\n",
        "import time\n",
        "from datetime import datetime\n",
        "import json"
      ],
      "metadata": {
        "id": "HhMaIkXlZKPC"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "GOOGLE_API_KEY = \"Use Your API Key Here\"\n",
        "NGROK_AUTH_TOKEN = \"Use Your Auth Token Here\"\n",
        "os.environ[\"GOOGLE_API_KEY\"] = GOOGLE_API_KEY"
      ],
      "metadata": {
        "id": "KMn4PiK-eX7S"
      },
      "execution_count": 11,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "class InnovativeAgentTools:\n",
        "    \"\"\"Advanced tool collection for the multi-agent system\"\"\"\n",
        "\n",
        "    @staticmethod\n",
        "    def get_calculator_tool():\n",
        "        def calculate(expression: str) -> str:\n",
        "            \"\"\"Calculate mathematical expressions safely\"\"\"\n",
        "            try:\n",
        "                allowed_chars = set('0123456789+-*/.() ')\n",
        "                if all(c in allowed_chars for c in expression):\n",
        "                    result = eval(expression)\n",
        "                    return f\"Result: {result}\"\n",
        "                else:\n",
        "                    return \"Error: Invalid mathematical expression\"\n",
        "            except Exception as e:\n",
        "                return f\"Calculation error: {str(e)}\"\n",
        "\n",
        "        return Tool(\n",
        "            name=\"Calculator\",\n",
        "            func=calculate,\n",
        "            description=\"Calculate mathematical expressions. Input should be a valid math expression.\"\n",
        "        )\n",
        "\n",
        "    @staticmethod\n",
        "    def get_memory_tool(memory_store):\n",
        "        def save_memory(key_value: str) -> str:\n",
        "            \"\"\"Save information to memory\"\"\"\n",
        "            try:\n",
        "                key, value = key_value.split(\":\", 1)\n",
        "                memory_store[key.strip()] = value.strip()\n",
        "                return f\"Saved '{key.strip()}' to memory\"\n",
        "            except:\n",
        "                return \"Error: Use format 'key: value'\"\n",
        "\n",
        "        def recall_memory(key: str) -> str:\n",
        "            \"\"\"Recall information from memory\"\"\"\n",
        "            return memory_store.get(key.strip(), f\"No memory found for '{key}'\")\n",
        "\n",
        "        return [\n",
        "            Tool(name=\"SaveMemory\", func=save_memory,\n",
        "                 description=\"Save information to memory. Format: 'key: value'\"),\n",
        "            Tool(name=\"RecallMemory\", func=recall_memory,\n",
        "                 description=\"Recall saved information. Input: key to recall\")\n",
        "        ]\n",
        "\n",
        "    @staticmethod\n",
        "    def get_datetime_tool():\n",
        "        def get_current_datetime(format_type: str = \"full\") -> str:\n",
        "            \"\"\"Get current date and time\"\"\"\n",
        "            now = datetime.now()\n",
        "            if format_type == \"date\":\n",
        "                return now.strftime(\"%Y-%m-%d\")\n",
        "            elif format_type == \"time\":\n",
        "                return now.strftime(\"%H:%M:%S\")\n",
        "            else:\n",
        "                return now.strftime(\"%Y-%m-%d %H:%M:%S\")\n",
        "\n",
        "        return Tool(\n",
        "            name=\"DateTime\",\n",
        "            func=get_current_datetime,\n",
        "            description=\"Get current date/time. Options: 'date', 'time', or 'full'\"\n",
        "        )"
      ],
      "metadata": {
        "id": "UgXRf7wSexVw"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "class MultiAgentSystem:\n",
        "    \"\"\"Innovative multi-agent system with specialized capabilities\"\"\"\n",
        "\n",
        "    def __init__(self, api_key: str):\n",
        "        self.llm = ChatGoogleGenerativeAI(\n",
        "            model=\"gemini-pro\",\n",
        "            google_api_key=api_key,\n",
        "            temperature=0.7,\n",
        "            convert_system_message_to_human=True\n",
        "        )\n",
        "        self.memory_store = {}\n",
        "        self.conversation_memory = ConversationBufferWindowMemory(\n",
        "            memory_key=\"chat_history\",\n",
        "            k=10,\n",
        "            return_messages=True\n",
        "        )\n",
        "        self.tools = self._initialize_tools()\n",
        "        self.agent = self._create_agent()\n",
        "\n",
        "    def _initialize_tools(self):\n",
        "        \"\"\"Initialize all available tools\"\"\"\n",
        "        tools = []\n",
        "\n",
        "        tools.extend([\n",
        "            DuckDuckGoSearchRun(api_wrapper=DuckDuckGoSearchAPIWrapper()),\n",
        "            WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())\n",
        "        ])\n",
        "\n",
        "        tools.append(InnovativeAgentTools.get_calculator_tool())\n",
        "        tools.append(InnovativeAgentTools.get_datetime_tool())\n",
        "        tools.extend(InnovativeAgentTools.get_memory_tool(self.memory_store))\n",
        "\n",
        "        return tools\n",
        "\n",
        "    def _create_agent(self):\n",
        "        \"\"\"Create the ReAct agent with advanced prompt\"\"\"\n",
        "        prompt = PromptTemplate.from_template(\"\"\"\n",
        "🤖 You are an advanced AI assistant with access to multiple tools and persistent memory.\n",
        "\n",
        "AVAILABLE TOOLS:\n",
        "{tools}\n",
        "\n",
        "TOOL USAGE FORMAT:\n",
        "- Think step by step about what you need to do\n",
        "- Use Action: tool_name\n",
        "- Use Action Input: your input\n",
        "- Wait for Observation\n",
        "- Continue until you have a final answer\n",
        "\n",
        "MEMORY CAPABILITIES:\n",
        "- You can save important information using SaveMemory\n",
        "- You can recall previous information using RecallMemory\n",
        "- Always try to remember user preferences and context\n",
        "\n",
        "CONVERSATION HISTORY:\n",
        "{chat_history}\n",
        "\n",
        "CURRENT QUESTION: {input}\n",
        "\n",
        "REASONING PROCESS:\n",
        "{agent_scratchpad}\n",
        "\n",
        "Begin your response with your thought process, then take action if needed.\n",
        "\"\"\")\n",
        "\n",
        "        agent = create_react_agent(self.llm, self.tools, prompt)\n",
        "        return AgentExecutor(\n",
        "            agent=agent,\n",
        "            tools=self.tools,\n",
        "            memory=self.conversation_memory,\n",
        "            verbose=True,\n",
        "            handle_parsing_errors=True,\n",
        "            max_iterations=5\n",
        "        )\n",
        "\n",
        "    def chat(self, message: str, callback_handler=None):\n",
        "        \"\"\"Process user message and return response\"\"\"\n",
        "        try:\n",
        "            if callback_handler:\n",
        "                response = self.agent.invoke(\n",
        "                    {\"input\": message},\n",
        "                    {\"callbacks\": [callback_handler]}\n",
        "                )\n",
        "            else:\n",
        "                response = self.agent.invoke({\"input\": message})\n",
        "            return response[\"output\"]\n",
        "        except Exception as e:\n",
        "            return f\"Error processing request: {str(e)}\""
      ],
      "metadata": {
        "id": "tUM7YilTe3zZ"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "def create_streamlit_app():\n",
        "    \"\"\"Create the innovative Streamlit application\"\"\"\n",
        "\n",
        "    st.set_page_config(\n",
        "        page_title=\"🚀 Advanced LangChain Agent with Gemini\",\n",
        "        page_icon=\"🤖\",\n",
        "        layout=\"wide\",\n",
        "        initial_sidebar_state=\"expanded\"\n",
        "    )\n",
        "\n",
        "    st.markdown(\"\"\"\n",
        "    <style>\n",
        "    .main-header {\n",
        "        background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);\n",
        "        padding: 1rem;\n",
        "        border-radius: 10px;\n",
        "        color: white;\n",
        "        text-align: center;\n",
        "        margin-bottom: 2rem;\n",
        "    }\n",
        "    .agent-response {\n",
        "        background-color: #f0f2f6;\n",
        "        padding: 1rem;\n",
        "        border-radius: 10px;\n",
        "        border-left: 4px solid #667eea;\n",
        "        margin: 1rem 0;\n",
        "    }\n",
        "    .memory-card {\n",
        "        background-color: #e8f4fd;\n",
        "        padding: 1rem;\n",
        "        border-radius: 8px;\n",
        "        margin: 0.5rem 0;\n",
        "    }\n",
        "    </style>\n",
        "    \"\"\", unsafe_allow_html=True)\n",
        "\n",
        "    st.markdown(\"\"\"\n",
        "    <div class=\"main-header\">\n",
        "        <h1>🚀 Advanced Multi-Agent System</h1>\n",
        "        <p>Powered by LangChain + Gemini API + Streamlit</p>\n",
        "    </div>\n",
        "    \"\"\", unsafe_allow_html=True)\n",
        "\n",
        "    with st.sidebar:\n",
        "        st.header(\"🔧 Configuration\")\n",
        "\n",
        "        api_key = st.text_input(\n",
        "            \"🔑 Google AI API Key\",\n",
        "            type=\"password\",\n",
        "            value=GOOGLE_API_KEY if GOOGLE_API_KEY != \"your-gemini-api-key-here\" else \"\",\n",
        "            help=\"Get your API key from https://ai.google.dev/\"\n",
        "        )\n",
        "\n",
        "        if not api_key:\n",
        "            st.error(\"Please enter your Google AI API key to continue\")\n",
        "            st.stop()\n",
        "\n",
        "        st.success(\"✅ API Key configured\")\n",
        "\n",
        "        st.header(\"🤖 Agent Capabilities\")\n",
        "        st.markdown(\"\"\"\n",
        "        - 🔍 **Web Search** (DuckDuckGo)\n",
        "        - 📚 **Wikipedia Lookup**\n",
        "        - 🧮 **Mathematical Calculator**\n",
        "        - 🧠 **Persistent Memory**\n",
        "        - 📅 **Date & Time**\n",
        "        - 💬 **Conversation History**\n",
        "        \"\"\")\n",
        "\n",
        "        if 'agent_system' in st.session_state:\n",
        "            st.header(\"🧠 Memory Store\")\n",
        "            memory = st.session_state.agent_system.memory_store\n",
        "            if memory:\n",
        "                for key, value in memory.items():\n",
        "                    st.markdown(f\"\"\"\n",
        "                    <div class=\"memory-card\">\n",
        "                        <strong>{key}:</strong> {value}\n",
        "                    </div>\n",
        "                    \"\"\", unsafe_allow_html=True)\n",
        "            else:\n",
        "                st.info(\"No memories stored yet\")\n",
        "\n",
        "    if 'agent_system' not in st.session_state:\n",
        "        with st.spinner(\"🔄 Initializing Advanced Agent System...\"):\n",
        "            st.session_state.agent_system = MultiAgentSystem(api_key)\n",
        "        st.success(\"✅ Agent System Ready!\")\n",
        "\n",
        "    st.header(\"💬 Interactive Chat\")\n",
        "\n",
        "    if 'messages' not in st.session_state:\n",
        "        st.session_state.messages = [{\n",
        "            \"role\": \"assistant\",\n",
        "            \"content\": \"\"\"🤖 Hello! I'm your advanced AI assistant powered by Gemini. I can:\n",
        "\n",
        "• Search the web and Wikipedia for information\n",
        "• Perform mathematical calculations\n",
        "• Remember important information across our conversation\n",
        "• Provide current date and time\n",
        "• Maintain conversation context\n",
        "\n",
        "Try asking me something like:\n",
        "- \"Calculate 15 * 8 + 32\"\n",
        "- \"Search for recent news about AI\"\n",
        "- \"Remember that my favorite color is blue\"\n",
        "- \"What's the current time?\"\n",
        "\"\"\"\n",
        "        }]\n",
        "\n",
        "    for message in st.session_state.messages:\n",
        "        with st.chat_message(message[\"role\"]):\n",
        "            st.markdown(message[\"content\"])\n",
        "\n",
        "    if prompt := st.chat_input(\"Ask me anything...\"):\n",
        "        st.session_state.messages.append({\"role\": \"user\", \"content\": prompt})\n",
        "        with st.chat_message(\"user\"):\n",
        "            st.markdown(prompt)\n",
        "\n",
        "        with st.chat_message(\"assistant\"):\n",
        "            callback_handler = StreamlitCallbackHandler(st.container())\n",
        "\n",
        "            with st.spinner(\"🤔 Thinking...\"):\n",
        "                response = st.session_state.agent_system.chat(prompt, callback_handler)\n",
        "\n",
        "            st.markdown(f\"\"\"\n",
        "            <div class=\"agent-response\">\n",
        "                {response}\n",
        "            </div>\n",
        "            \"\"\", unsafe_allow_html=True)\n",
        "\n",
        "            st.session_state.messages.append({\"role\": \"assistant\", \"content\": response})\n",
        "\n",
        "    st.header(\"💡 Example Queries\")\n",
        "    col1, col2, col3 = st.columns(3)\n",
        "\n",
        "    with col1:\n",
        "        if st.button(\"🔍 Search Example\"):\n",
        "            example = \"Search for the latest developments in quantum computing\"\n",
        "            st.session_state.example_query = example\n",
        "\n",
        "    with col2:\n",
        "        if st.button(\"🧮 Math Example\"):\n",
        "            example = \"Calculate the compound interest on $1000 at 5% for 3 years\"\n",
        "            st.session_state.example_query = example\n",
        "\n",
        "    with col3:\n",
        "        if st.button(\"🧠 Memory Example\"):\n",
        "            example = \"Remember that I work as a data scientist at TechCorp\"\n",
        "            st.session_state.example_query = example\n",
        "\n",
        "    if 'example_query' in st.session_state:\n",
        "        st.info(f\"Example query: {st.session_state.example_query}\")"
      ],
      "metadata": {
        "id": "UWFm3K7Ce8sM"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "def setup_ngrok_auth(auth_token):\n",
        "    \"\"\"Setup ngrok authentication\"\"\"\n",
        "    try:\n",
        "        from pyngrok import ngrok, conf\n",
        "\n",
        "        conf.get_default().auth_token = auth_token\n",
        "\n",
        "        try:\n",
        "            tunnels = ngrok.get_tunnels()\n",
        "            print(\"✅ Ngrok authentication successful!\")\n",
        "            return True\n",
        "        except Exception as e:\n",
        "            print(f\"❌ Ngrok authentication failed: {e}\")\n",
        "            return False\n",
        "\n",
        "    except ImportError:\n",
        "        print(\"❌ pyngrok not installed. Installing...\")\n",
        "        import subprocess\n",
        "        subprocess.run(['pip', 'install', 'pyngrok'], check=True)\n",
        "        return setup_ngrok_auth(auth_token)\n",
        "\n",
        "def get_ngrok_token_instructions():\n",
        "    \"\"\"Provide instructions for getting ngrok token\"\"\"\n",
        "    return \"\"\"\n",
        "🔧 NGROK AUTHENTICATION SETUP:\n",
        "\n",
        "1. Sign up for a free ngrok account:\n",
        "   - Visit: https://dashboard.ngrok.com/signup\n",
        "   - Create a free account\n",
        "\n",
        "2. Get your authentication token:\n",
        "   - Go to: https://dashboard.ngrok.com/get-started/your-authtoken\n",
        "   - Copy your authtoken\n",
        "\n",
        "3. Replace 'your-ngrok-auth-token-here' in the code with your actual token\n",
        "\n",
        "4. Alternative methods if ngrok fails:\n",
        "   - Use Google Colab's built-in public URL feature\n",
        "   - Use localtunnel: !npx localtunnel --port 8501\n",
        "   - Use serveo.net: !ssh -R 80:localhost:8501 serveo.net\n",
        "\"\"\""
      ],
      "metadata": {
        "id": "5S4nKNv9fCXh"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "def main():\n",
        "    \"\"\"Main function to run the application\"\"\"\n",
        "    try:\n",
        "        create_streamlit_app()\n",
        "    except Exception as e:\n",
        "        st.error(f\"Application error: {str(e)}\")\n",
        "        st.info(\"Please check your API key and try refreshing the page\")"
      ],
      "metadata": {
        "id": "dq93_VNyfL8u"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "def run_in_colab():\n",
        "    \"\"\"Run the application in Google Colab with proper ngrok setup\"\"\"\n",
        "\n",
        "    print(\"🚀 Starting Advanced LangChain Agent Setup...\")\n",
        "\n",
        "    if NGROK_AUTH_TOKEN == \"your-ngrok-auth-token-here\":\n",
        "        print(\"⚠️  NGROK_AUTH_TOKEN not configured!\")\n",
        "        print(get_ngrok_token_instructions())\n",
        "\n",
        "        print(\"🔄 Attempting alternative tunnel methods...\")\n",
        "        try_alternative_tunnels()\n",
        "        return\n",
        "\n",
        "    print(\"📦 Installing required packages...\")\n",
        "    import subprocess\n",
        "\n",
        "    packages = [\n",
        "        'streamlit',\n",
        "        'langchain',\n",
        "        'langchain-google-genai',\n",
        "        'langchain-community',\n",
        "        'wikipedia',\n",
        "        'duckduckgo-search',\n",
        "        'pyngrok'\n",
        "    ]\n",
        "\n",
        "    for package in packages:\n",
        "        try:\n",
        "            subprocess.run(['pip', 'install', package], check=True, capture_output=True)\n",
        "            print(f\"✅ {package} installed\")\n",
        "        except subprocess.CalledProcessError:\n",
        "            print(f\"⚠️  Failed to install {package}\")\n",
        "\n",
        "    app_content = '''\n",
        "import streamlit as st\n",
        "import os\n",
        "from langchain_google_genai import ChatGoogleGenerativeAI\n",
        "from langchain.agents import create_react_agent, AgentExecutor\n",
        "from langchain.tools import Tool, WikipediaQueryRun, DuckDuckGoSearchRun\n",
        "from langchain.memory import ConversationBufferWindowMemory\n",
        "from langchain.prompts import PromptTemplate\n",
        "from langchain.callbacks.streamlit import StreamlitCallbackHandler\n",
        "from langchain_community.utilities import WikipediaAPIWrapper, DuckDuckGoSearchAPIWrapper\n",
        "from datetime import datetime\n",
        "\n",
        "# Configuration - Replace with your actual keys\n",
        "GOOGLE_API_KEY = \"''' + GOOGLE_API_KEY + '''\"\n",
        "os.environ[\"GOOGLE_API_KEY\"] = GOOGLE_API_KEY\n",
        "\n",
        "class InnovativeAgentTools:\n",
        "    @staticmethod\n",
        "    def get_calculator_tool():\n",
        "        def calculate(expression: str) -> str:\n",
        "            try:\n",
        "                allowed_chars = set('0123456789+-*/.() ')\n",
        "                if all(c in allowed_chars for c in expression):\n",
        "                    result = eval(expression)\n",
        "                    return f\"Result: {result}\"\n",
        "                else:\n",
        "                    return \"Error: Invalid mathematical expression\"\n",
        "            except Exception as e:\n",
        "                return f\"Calculation error: {str(e)}\"\n",
        "\n",
        "        return Tool(name=\"Calculator\", func=calculate,\n",
        "                   description=\"Calculate mathematical expressions. Input should be a valid math expression.\")\n",
        "\n",
        "    @staticmethod\n",
        "    def get_memory_tool(memory_store):\n",
        "        def save_memory(key_value: str) -> str:\n",
        "            try:\n",
        "                key, value = key_value.split(\":\", 1)\n",
        "                memory_store[key.strip()] = value.strip()\n",
        "                return f\"Saved '{key.strip()}' to memory\"\n",
        "            except:\n",
        "                return \"Error: Use format 'key: value'\"\n",
        "\n",
        "        def recall_memory(key: str) -> str:\n",
        "            return memory_store.get(key.strip(), f\"No memory found for '{key}'\")\n",
        "\n",
        "        return [\n",
        "            Tool(name=\"SaveMemory\", func=save_memory, description=\"Save information to memory. Format: 'key: value'\"),\n",
        "            Tool(name=\"RecallMemory\", func=recall_memory, description=\"Recall saved information. Input: key to recall\")\n",
        "        ]\n",
        "\n",
        "    @staticmethod\n",
        "    def get_datetime_tool():\n",
        "        def get_current_datetime(format_type: str = \"full\") -> str:\n",
        "            now = datetime.now()\n",
        "            if format_type == \"date\":\n",
        "                return now.strftime(\"%Y-%m-%d\")\n",
        "            elif format_type == \"time\":\n",
        "                return now.strftime(\"%H:%M:%S\")\n",
        "            else:\n",
        "                return now.strftime(\"%Y-%m-%d %H:%M:%S\")\n",
        "\n",
        "        return Tool(name=\"DateTime\", func=get_current_datetime,\n",
        "                   description=\"Get current date/time. Options: 'date', 'time', or 'full'\")\n",
        "\n",
        "class MultiAgentSystem:\n",
        "    def __init__(self, api_key: str):\n",
        "        self.llm = ChatGoogleGenerativeAI(\n",
        "            model=\"gemini-pro\",\n",
        "            google_api_key=api_key,\n",
        "            temperature=0.7,\n",
        "            convert_system_message_to_human=True\n",
        "        )\n",
        "        self.memory_store = {}\n",
        "        self.conversation_memory = ConversationBufferWindowMemory(\n",
        "            memory_key=\"chat_history\", k=10, return_messages=True\n",
        "        )\n",
        "        self.tools = self._initialize_tools()\n",
        "        self.agent = self._create_agent()\n",
        "\n",
        "    def _initialize_tools(self):\n",
        "        tools = []\n",
        "        try:\n",
        "            tools.extend([\n",
        "                DuckDuckGoSearchRun(api_wrapper=DuckDuckGoSearchAPIWrapper()),\n",
        "                WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())\n",
        "            ])\n",
        "        except Exception as e:\n",
        "            st.warning(f\"Search tools may have limited functionality: {e}\")\n",
        "\n",
        "        tools.append(InnovativeAgentTools.get_calculator_tool())\n",
        "        tools.append(InnovativeAgentTools.get_datetime_tool())\n",
        "        tools.extend(InnovativeAgentTools.get_memory_tool(self.memory_store))\n",
        "        return tools\n",
        "\n",
        "    def _create_agent(self):\n",
        "        prompt = PromptTemplate.from_template(\"\"\"\n",
        "🤖 You are an advanced AI assistant with access to multiple tools and persistent memory.\n",
        "\n",
        "AVAILABLE TOOLS:\n",
        "{tools}\n",
        "\n",
        "TOOL USAGE FORMAT:\n",
        "- Think step by step about what you need to do\n",
        "- Use Action: tool_name\n",
        "- Use Action Input: your input\n",
        "- Wait for Observation\n",
        "- Continue until you have a final answer\n",
        "\n",
        "CONVERSATION HISTORY:\n",
        "{chat_history}\n",
        "\n",
        "CURRENT QUESTION: {input}\n",
        "\n",
        "REASONING PROCESS:\n",
        "{agent_scratchpad}\n",
        "\n",
        "Begin your response with your thought process, then take action if needed.\n",
        "\"\"\")\n",
        "\n",
        "        agent = create_react_agent(self.llm, self.tools, prompt)\n",
        "        return AgentExecutor(agent=agent, tools=self.tools, memory=self.conversation_memory,\n",
        "                           verbose=True, handle_parsing_errors=True, max_iterations=5)\n",
        "\n",
        "    def chat(self, message: str, callback_handler=None):\n",
        "        try:\n",
        "            if callback_handler:\n",
        "                response = self.agent.invoke({\"input\": message}, {\"callbacks\": [callback_handler]})\n",
        "            else:\n",
        "                response = self.agent.invoke({\"input\": message})\n",
        "            return response[\"output\"]\n",
        "        except Exception as e:\n",
        "            return f\"Error processing request: {str(e)}\"\n",
        "\n",
        "# Streamlit App\n",
        "st.set_page_config(page_title=\"🚀 Advanced LangChain Agent\", page_icon=\"🤖\", layout=\"wide\")\n",
        "\n",
        "st.markdown(\"\"\"\n",
        "<style>\n",
        ".main-header {\n",
        "    background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);\n",
        "    padding: 1rem; border-radius: 10px; color: white; text-align: center; margin-bottom: 2rem;\n",
        "}\n",
        ".agent-response {\n",
        "    background-color: #f0f2f6; padding: 1rem; border-radius: 10px;\n",
        "    border-left: 4px solid #667eea; margin: 1rem 0;\n",
        "}\n",
        ".memory-card {\n",
        "    background-color: #e8f4fd; padding: 1rem; border-radius: 8px; margin: 0.5rem 0;\n",
        "}\n",
        "</style>\n",
        "\"\"\", unsafe_allow_html=True)\n",
        "\n",
        "st.markdown('<div class=\"main-header\"><h1>🚀 Advanced Multi-Agent System</h1><p>Powered by LangChain + Gemini API</p></div>', unsafe_allow_html=True)\n",
        "\n",
        "with st.sidebar:\n",
        "    st.header(\"🔧 Configuration\")\n",
        "    api_key = st.text_input(\"🔑 Google AI API Key\", type=\"password\", value=GOOGLE_API_KEY)\n",
        "\n",
        "    if not api_key:\n",
        "        st.error(\"Please enter your Google AI API key\")\n",
        "        st.stop()\n",
        "\n",
        "    st.success(\"✅ API Key configured\")\n",
        "\n",
        "    st.header(\"🤖 Agent Capabilities\")\n",
        "    st.markdown(\"- 🔍 Web Search\\\\n- 📚 Wikipedia\\\\n- 🧮 Calculator\\\\n- 🧠 Memory\\\\n- 📅 Date/Time\")\n",
        "\n",
        "    if 'agent_system' in st.session_state and st.session_state.agent_system.memory_store:\n",
        "        st.header(\"🧠 Memory Store\")\n",
        "        for key, value in st.session_state.agent_system.memory_store.items():\n",
        "            st.markdown(f'<div class=\"memory-card\"><strong>{key}:</strong> {value}</div>', unsafe_allow_html=True)\n",
        "\n",
        "if 'agent_system' not in st.session_state:\n",
        "    with st.spinner(\"🔄 Initializing Agent...\"):\n",
        "        st.session_state.agent_system = MultiAgentSystem(api_key)\n",
        "    st.success(\"✅ Agent Ready!\")\n",
        "\n",
        "if 'messages' not in st.session_state:\n",
        "    st.session_state.messages = [{\n",
        "        \"role\": \"assistant\",\n",
        "        \"content\": \"🤖 Hello! I'm your advanced AI assistant. I can search, calculate, remember information, and more! Try asking me to: calculate something, search for information, or remember a fact about you.\"\n",
        "    }]\n",
        "\n",
        "for message in st.session_state.messages:\n",
        "    with st.chat_message(message[\"role\"]):\n",
        "        st.markdown(message[\"content\"])\n",
        "\n",
        "if prompt := st.chat_input(\"Ask me anything...\"):\n",
        "    st.session_state.messages.append({\"role\": \"user\", \"content\": prompt})\n",
        "    with st.chat_message(\"user\"):\n",
        "        st.markdown(prompt)\n",
        "\n",
        "    with st.chat_message(\"assistant\"):\n",
        "        callback_handler = StreamlitCallbackHandler(st.container())\n",
        "        with st.spinner(\"🤔 Thinking...\"):\n",
        "            response = st.session_state.agent_system.chat(prompt, callback_handler)\n",
        "        st.markdown(f'<div class=\"agent-response\">{response}</div>', unsafe_allow_html=True)\n",
        "        st.session_state.messages.append({\"role\": \"assistant\", \"content\": response})\n",
        "\n",
        "# Example buttons\n",
        "st.header(\"💡 Try These Examples\")\n",
        "col1, col2, col3 = st.columns(3)\n",
        "with col1:\n",
        "    if st.button(\"🧮 Calculate 15 * 8 + 32\"):\n",
        "        st.rerun()\n",
        "with col2:\n",
        "    if st.button(\"🔍 Search AI news\"):\n",
        "        st.rerun()\n",
        "with col3:\n",
        "    if st.button(\"🧠 Remember my name is Alex\"):\n",
        "        st.rerun()\n",
        "'''\n",
        "\n",
        "    with open('streamlit_app.py', 'w') as f:\n",
        "        f.write(app_content)\n",
        "\n",
        "    print(\"✅ Streamlit app file created successfully!\")\n",
        "\n",
        "    if setup_ngrok_auth(NGROK_AUTH_TOKEN):\n",
        "        start_streamlit_with_ngrok()\n",
        "    else:\n",
        "        print(\"❌ Ngrok authentication failed. Trying alternative methods...\")\n",
        "        try_alternative_tunnels()"
      ],
      "metadata": {
        "id": "_6dx5fVpfIrh"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "def start_streamlit_with_ngrok():\n",
        "    \"\"\"Start Streamlit with ngrok tunnel\"\"\"\n",
        "    import subprocess\n",
        "    import threading\n",
        "    from pyngrok import ngrok\n",
        "\n",
        "    def start_streamlit():\n",
        "        subprocess.run(['streamlit', 'run', 'streamlit_app.py', '--server.port=8501', '--server.headless=true'])\n",
        "\n",
        "    print(\"🚀 Starting Streamlit server...\")\n",
        "    thread = threading.Thread(target=start_streamlit)\n",
        "    thread.daemon = True\n",
        "    thread.start()\n",
        "\n",
        "    time.sleep(5)\n",
        "\n",
        "    try:\n",
        "        print(\"🌐 Creating ngrok tunnel...\")\n",
        "        public_url = ngrok.connect(8501)\n",
        "        print(f\"🔗 SUCCESS! Access your app at: {public_url}\")\n",
        "        print(\"✨ Your Advanced LangChain Agent is now running publicly!\")\n",
        "        print(\"📱 You can share this URL with others!\")\n",
        "\n",
        "        print(\"⏳ Keeping tunnel alive... Press Ctrl+C to stop\")\n",
        "        try:\n",
        "            ngrok_process = ngrok.get_ngrok_process()\n",
        "            ngrok_process.proc.wait()\n",
        "        except KeyboardInterrupt:\n",
        "            print(\"👋 Shutting down...\")\n",
        "            ngrok.kill()\n",
        "\n",
        "    except Exception as e:\n",
        "        print(f\"❌ Ngrok tunnel failed: {e}\")\n",
        "        try_alternative_tunnels()\n",
        "\n",
        "def try_alternative_tunnels():\n",
        "    \"\"\"Try alternative tunneling methods\"\"\"\n",
        "    print(\"🔄 Trying alternative tunnel methods...\")\n",
        "\n",
        "    import subprocess\n",
        "    import threading\n",
        "\n",
        "    def start_streamlit():\n",
        "        subprocess.run(['streamlit', 'run', 'streamlit_app.py', '--server.port=8501', '--server.headless=true'])\n",
        "\n",
        "    thread = threading.Thread(target=start_streamlit)\n",
        "    thread.daemon = True\n",
        "    thread.start()\n",
        "\n",
        "    time.sleep(3)\n",
        "\n",
        "    print(\"🌐 Streamlit is running on http://localhost:8501\")\n",
        "    print(\"\\n📋 ALTERNATIVE TUNNEL OPTIONS:\")\n",
        "    print(\"1. localtunnel: Run this in a new cell:\")\n",
        "    print(\"   !npx localtunnel --port 8501\")\n",
        "    print(\"\\n2. serveo.net: Run this in a new cell:\")\n",
        "    print(\"   !ssh -R 80:localhost:8501 serveo.net\")\n",
        "    print(\"\\n3. Colab public URL (if available):\")\n",
        "    print(\"   Use the 'Public URL' button in Colab's interface\")\n",
        "\n",
        "    try:\n",
        "        while True:\n",
        "            time.sleep(60)\n",
        "    except KeyboardInterrupt:\n",
        "        print(\"👋 Shutting down...\")\n",
        "\n",
        "if __name__ == \"__main__\":\n",
        "    try:\n",
        "        get_ipython()\n",
        "        print(\"🚀 Google Colab detected - starting setup...\")\n",
        "        run_in_colab()\n",
        "    except NameError:\n",
        "        main()"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "5-g0wgdqboHv",
        "outputId": "e6dc86b5-9442-4a24-beaa-f5e384a80a01"
      },
      "execution_count": 10,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "🚀 Google Colab detected - starting setup...\n",
            "🚀 Starting Advanced LangChain Agent Setup...\n",
            "📦 Installing required packages...\n",
            "✅ streamlit installed\n",
            "✅ langchain installed\n",
            "✅ langchain-google-genai installed\n",
            "✅ langchain-community installed\n",
            "✅ wikipedia installed\n",
            "✅ duckduckgo-search installed\n",
            "✅ pyngrok installed\n",
            "✅ Streamlit app file created successfully!\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "ERROR:pyngrok.process.ngrok:t=2025-06-16T16:01:43+0000 lvl=eror msg=\"failed to reconnect session\" obj=tunnels.session err=\"authentication failed: The authtoken you specified is properly formed, but it is invalid.\\nYour authtoken: 2yb2TRydBkNbaecL2WjnhEsXy5n_qyQpZ7g9NPTDvZNdQuJU\\nThis usually happens when:\\n    - You reset your authtoken\\n    - Your authtoken was for a team account that you were removed from\\n    - You are using ngrok link and this credential was explicitly revoked\\nGo to your ngrok dashboard and double check that your authtoken is correct:\\nhttps://dashboard.ngrok.com/get-started/your-authtoken\\r\\n\\r\\nERR_NGROK_107\\r\\n\"\n",
            "ERROR:pyngrok.process.ngrok:t=2025-06-16T16:01:43+0000 lvl=eror msg=\"session closing\" obj=tunnels.session err=\"authentication failed: The authtoken you specified is properly formed, but it is invalid.\\nYour authtoken: 2yb2TRydBkNbaecL2WjnhEsXy5n_qyQpZ7g9NPTDvZNdQuJU\\nThis usually happens when:\\n    - You reset your authtoken\\n    - Your authtoken was for a team account that you were removed from\\n    - You are using ngrok link and this credential was explicitly revoked\\nGo to your ngrok dashboard and double check that your authtoken is correct:\\nhttps://dashboard.ngrok.com/get-started/your-authtoken\\r\\n\\r\\nERR_NGROK_107\\r\\n\"\n",
            "ERROR:pyngrok.process.ngrok:t=2025-06-16T16:01:43+0000 lvl=eror msg=\"terminating with error\" obj=app err=\"authentication failed: The authtoken you specified is properly formed, but it is invalid.\\nYour authtoken: 2yb2TRydBkNbaecL2WjnhEsXy5n_qyQpZ7g9NPTDvZNdQuJU\\nThis usually happens when:\\n    - You reset your authtoken\\n    - Your authtoken was for a team account that you were removed from\\n    - You are using ngrok link and this credential was explicitly revoked\\nGo to your ngrok dashboard and double check that your authtoken is correct:\\nhttps://dashboard.ngrok.com/get-started/your-authtoken\\r\\n\\r\\nERR_NGROK_107\\r\\n\"\n",
            "CRITICAL:pyngrok.process.ngrok:t=2025-06-16T16:01:43+0000 lvl=crit msg=\"command failed\" err=\"authentication failed: The authtoken you specified is properly formed, but it is invalid.\\nYour authtoken: 2yb2TRydBkNbaecL2WjnhEsXy5n_qyQpZ7g9NPTDvZNdQuJU\\nThis usually happens when:\\n    - You reset your authtoken\\n    - Your authtoken was for a team account that you were removed from\\n    - You are using ngrok link and this credential was explicitly revoked\\nGo to your ngrok dashboard and double check that your authtoken is correct:\\nhttps://dashboard.ngrok.com/get-started/your-authtoken\\r\\n\\r\\nERR_NGROK_107\\r\\n\"\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "❌ Ngrok authentication failed: The ngrok process errored on start: authentication failed: The authtoken you specified is properly formed, but it is invalid.\\nYour authtoken: 2yb2TRydBkNbaecL2WjnhEsXy5n_qyQpZ7g9NPTDvZNdQuJU\\nThis usually happens when:\\n    - You reset your authtoken\\n    - Your authtoken was for a team account that you were removed from\\n    - You are using ngrok link and this credential was explicitly revoked\\nGo to your ngrok dashboard and double check that your authtoken is correct:\\nhttps://dashboard.ngrok.com/get-started/your-authtoken\\r\\n\\r\\nERR_NGROK_107\\r\\n.\n",
            "❌ Ngrok authentication failed. Trying alternative methods...\n",
            "🔄 Trying alternative tunnel methods...\n",
            "🌐 Streamlit is running on http://localhost:8501\n",
            "\n",
            "📋 ALTERNATIVE TUNNEL OPTIONS:\n",
            "1. localtunnel: Run this in a new cell:\n",
            "   !npx localtunnel --port 8501\n",
            "\n",
            "2. serveo.net: Run this in a new cell:\n",
            "   !ssh -R 80:localhost:8501 serveo.net\n",
            "\n",
            "3. Colab public URL (if available):\n",
            "   Use the 'Public URL' button in Colab's interface\n",
            "👋 Shutting down...\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "!npx localtunnel --port 8501"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "fTI29gEldRU4",
        "outputId": "11e0102a-b54e-4335-eb12-3497f5368391"
      },
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "\u001b[1G\u001b[0K⠙\u001b[1G\u001b[0K⠹\u001b[1G\u001b[0K⠸\u001b[1G\u001b[0K⠼\u001b[1G\u001b[0K⠴\u001b[1G\u001b[0K⠦\u001b[1G\u001b[0K⠧\u001b[1G\u001b[0K⠇\u001b[1G\u001b[0Kyour url is: https://loud-lights-live.loca.lt\n",
            "^C\n"
          ]
        }
      ]
    }
  ]
}